﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AutoMapper;
using System.Diagnostics.CodeAnalysis;
using System.Data;
using AutoMapper.Mappers;

namespace Steve.EFDataLayer
{
    [SuppressMessage("Microsoft.Maintainability", "CA1505:AvoidUnmaintainableCode")]
    internal static class SteveEFDataLayer
    {
        [SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase", Justification="Mime types must be lower case")]
        [SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling")]
        [SuppressMessage("Microsoft.Maintainability", "CA1505:AvoidUnmaintainableCode", Justification = "Only run once, complex due to lambdas in syntax")]
        [SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification = "Only run once, complex due to lambdas in syntax")]
        public static void SetupAutoMapper()
        {
            Mapper.CreateMap<DbSite, Site>()
                .ForMember(dest => dest.IsNew, opt => opt.UseValue(false))
                .ForMember(dest => dest.AlternateAuthorities, opt => opt.Ignore())
                .ForMember(dest => dest.IsManagedSite, opt => opt.MapFrom(src => src.IsManaged))
                .ForMember(dest => dest.Authority, opt => opt.MapFrom(src => src.DefaultAuthority))
                .ForMember(dest => dest.CreateDate, opt => opt.MapFrom(src => src.CreateDate))
                .ForMember(dest => dest.RevisionDate, opt => opt.MapFrom(src => src.UpdateDate))
                .ForMember(dest => dest.RevisionMembershipId, opt => opt.MapFrom(src => src.UpdateMembershipId));

            Mapper.CreateMap<Site, DbSite>()
                .ForMember(dest => dest.EntityKey, opt => opt.Ignore())
                .ForMember(dest => dest.SiteUrls, opt => opt.Ignore())
                .ForMember(dest => dest.UrlRewrites, opt => opt.Ignore())
                .ForMember(dest => dest.CreateDate, opt => opt.Ignore())
                .ForMember(dest => dest.CreateMembershipId, opt => opt.Ignore())

                .ForMember(dest => dest.UpdateDate, opt => opt.MapFrom(src => src.RevisionDate))
                .ForMember(dest => dest.UpdateMembershipId, opt => opt.MapFrom(src => src.RevisionMembershipId))
                .ForMember(dest => dest.DefaultAuthority, opt => opt.MapFrom(src => src.Authority))
                .ForMember(dest => dest.IsManaged, opt => opt.MapFrom(src => src.IsManagedSite));

            Mapper.CreateMap<DbSiteUrl, SiteUrl>()
                .ForMember(dest => dest.IsNew, opt => opt.UseValue(false))
                .ForMember(dest => dest.RevisionNumber, opts => opts.MapFrom(src => src.LatestRevisionNumber))
                .ForMember(dest => dest.CreateDate, opts => opts.MapFrom(src => src.CreateDate))
                .ForMember(dest => dest.Start, opts => opts.MapFrom(src => src.StartDate))
                .ForMember(dest => dest.End, opts => opts.MapFrom(src => src.EndDate));

            Mapper.CreateMap<SiteUrl, DbSiteUrl>()
                .ForMember(dest => dest.EntityKey, opt => opt.Ignore())
                .ForMember(dest => dest.Site, opt => opt.Ignore())
                .ForMember(dest => dest.SiteReference, opt => opt.Ignore())
                .ForMember(dest => dest.UrlRewrites, opt => opt.Ignore())
                .ForMember(dest => dest.PageMetaDescription, opt => opt.Ignore())
                .ForMember(dest => dest.PageMetaKeywords, opt => opt.Ignore())
                .ForMember(dest => dest.PageTitle, opt => opt.Ignore())
                .ForMember(dest => dest.CreateDate, opt => opt.Ignore())
                .ForMember(dest => dest.CreateMembershipId, opt => opt.Ignore())

                .ForMember(dest => dest.SiteName, opt => opt.Condition(src => src.IsNew))
                .ForMember(dest => dest.Url, opt => opt.Condition(src => src.IsNew))
                .ForMember(dest => dest.ExternalId, opt => opt.Condition(src => src.IsNew))
                .ForMember(dest => dest.SystemName, opt => opt.Condition(src => src.IsNew))

                .ForMember(dest => dest.StartDate, opt => opt.MapFrom(src => src.Start))
                .ForMember(dest => dest.EndDate, opt => opt.MapFrom(src => src.End));


            Mapper.CreateMap<DbUrlRewrite, RewriteUrl>()
                .ForMember(dest => dest.IsNew, opt => opt.UseValue(false))
                .ForMember(dest => dest.RevisionNumber, opts => opts.MapFrom(src => src.LatestRevisionNumber))
                .ForMember(dest => dest.CreateDate, opts => opts.MapFrom(src => src.CreateDate))
                .ForMember(dest => dest.Start, opts => opts.MapFrom(src => src.StartDate))
                .ForMember(dest => dest.End, opts => opts.MapFrom(src => src.EndDate));

            Mapper.CreateMap<RewriteUrl, DbUrlRewrite>()
                .ForMember(dest => dest.EntityKey, opt => opt.Ignore())
                .ForMember(dest => dest.Site, opt => opt.Ignore())
                .ForMember(dest => dest.SiteUrl, opt => opt.Ignore())
                .ForMember(dest => dest.SiteUrlReference, opt => opt.Ignore())
                .ForMember(dest => dest.SiteReference, opt => opt.Ignore())
                .ForMember(dest => dest.CreateDate, opt => opt.Ignore())
                .ForMember(dest => dest.CreateMembershipId, opt => opt.Ignore())

                .ForMember(dest => dest.SiteName, opt => opt.Condition(src => src.IsNew))
                .ForMember(dest => dest.Url, opt => opt.Condition(src => src.IsNew))
                .ForMember(dest => dest.ExternalId, opt => opt.Condition(src => src.IsNew))
                .ForMember(dest => dest.SystemName, opt => opt.Condition(src => src.IsNew))

                .ForMember(dest => dest.StartDate, opt => opt.MapFrom(src => src.Start))
                .ForMember(dest => dest.EndDate, opt => opt.MapFrom(src => src.End));

            Mapper.CreateMap<Content, DbContent>()
                .ForMember(dest => dest.EntityKey, opt => opt.Ignore())
                .ForMember(dest => dest.ContentData, opt => opt.Ignore())
                .ForMember(dest => dest.ContentDataReference, opt => opt.Ignore())
                .ForMember(dest => dest.ContentType, opt => opt.Ignore())
                .ForMember(dest => dest.ContentTypeReference, opt => opt.Ignore())
                .ForMember(dest => dest.PublisherUrlId, opt => opt.Ignore())
                .ForMember(dest => dest.ThumbnailContentId, opt => opt.Ignore())
                .ForMember(dest => dest.ApprovalDate, opt => opt.Ignore())
                .ForMember(dest => dest.ApprovalMembershipId, opt => opt.Ignore())
                .ForMember(dest => dest.RevisionNumber, opt => opt.Ignore())
                .ForMember(dest => dest.LatestApprovedRevisionNumber, opt => opt.Ignore())
                .ForMember(dest => dest.LatestRevisionNumber, opt => opt.Ignore())

                .ForMember(dest => dest.ContentTypeName, opt => opt.Condition((Content src) => src.IsNew))
                .ForMember(dest => dest.SystemName, opt => opt.Condition((Content src) => src.IsNew))
                .ForMember(dest => dest.ExternalId, opt => opt.Condition((Content src) => src.IsNew))
                .ForMember(dest => dest.Language, opt => opt.Condition((Content src) => src.IsNew))

                //TODO: catagories?
                .ForMember(dest => dest.MimeType, opt => opt.MapFrom(src => src.MimeType == null ? (string)null : src.MimeType.Value.ToString("g").ToLowerInvariant()));


            Mapper.CreateMap<DbContent, Content>()
                .ForMember(dest => dest.IsNew, opt => opt.Ignore())

                .ForMember(dest => dest.RevisionNumber, opt => opt.MapFrom(src => src.LatestRevisionNumber))
                .ForMember(dest => dest.MimeType, opt => opt.MapFrom(src => string.IsNullOrWhiteSpace(src.MimeType) ? (MimeType?)null : (MimeType?)Enum.Parse(typeof(MimeType), src.MimeType, true)));

            Mapper.CreateMap<Category, DbCategory>()
                .ForMember(dest => dest.EntityKey, opt => opt.Ignore())

                .ForMember(dest => dest.IsUserTag, opt => opt.UseValue(false))

                .ForMember(dest => dest.UpdateDate, opt => opt.MapFrom(src => src.RevisionDate))
                .ForMember(dest => dest.UpdateMembershipId, opt => opt.MapFrom(src => src.RevisionMembershipId));

            Mapper.CreateMap<DbCategory, Category>()
                .ForMember(dest => dest.IsNew, opt => opt.UseValue(false))
                .ForMember(dest => dest.CreateDate, opt => opt.MapFrom(src => src.CreateDate))
                .ForMember(dest => dest.RevisionDate, opt => opt.MapFrom(src => src.UpdateDate))
                .ForMember(dest => dest.RevisionMembershipId, opt => opt.MapFrom(src => src.UpdateMembershipId));

            Mapper.CreateMap<DbDataUpdate, DataUpdate>()
                .ForMember(dest => dest.UpdateComment, opt => opt.MapFrom(src => src.RevisionComment))
                .ForMember(dest => dest.UpdateDate, opt => opt.MapFrom(src => src.RevisionDate))
                .ForMember(dest => dest.UpdateMembershipId, opt => opt.MapFrom(src => src.RevisionMembershipId))
                .ForMember(dest => dest.UpdateNumber, opt => opt.MapFrom(src => src.RevisionNumber));

            Mapper.CreateMap<DbSystem, ExternalSystem>();

            Mapper.CreateMap<IDataRecord, Content>()
                .ForMember(dest => dest.Language, opt => opt.Ignore())
                .ForMember(dest => dest.SystemName, opt => opt.Ignore())
                .ForMember(dest => dest.ExternalId, opt => opt.Ignore())
                .ForMember(dest => dest.Path, opt => opt.Ignore())
                .ForMember(dest => dest.ContentTypeName, opt => opt.Ignore())
                .ForMember(dest => dest.SiteUrlId, opt => opt.Ignore())
                .ForMember(dest => dest.LatestApprovedRevisionNumber, opt => opt.Ignore())
                .ForMember(dest => dest.Height, opt => opt.Ignore())
                .ForMember(dest => dest.Width, opt => opt.Ignore())
                .ForMember(dest => dest.Title, opt => opt.Ignore())
                .ForMember(dest => dest.Teaser, opt => opt.Ignore())
                .ForMember(dest => dest.PublicationDate, opt => opt.Ignore())
                .ForMember(dest => dest.Publisher, opt => opt.Ignore())
                .ForMember(dest => dest.ApprovalDate, opt => opt.Ignore())
                .ForMember(dest => dest.ApprovalMembershipId, opt => opt.Ignore())
                .ForMember(dest => dest.MimeType, opt => opt.Ignore())
                .ForMember(dest => dest.MimeSubtype, opt => opt.Ignore())
                .ForMember(dest => dest.ContentDataId, opt => opt.Ignore())
                .ForMember(dest => dest.Author, opt => opt.Ignore())
                .ForMember(dest => dest.LatestRevisionNumber, opt => opt.Ignore())
                .ForMember(dest => dest.RevisionComment, opt => opt.Ignore())
                .ForMember(dest => dest.RevisionNumber, opt => opt.Ignore())
                .ForMember(dest => dest.CreateDate, opt => opt.Ignore())
                .ForMember(dest => dest.CreateMembershipId, opt => opt.Ignore())
                .ForMember(dest => dest.RevisionMembershipId, opt => opt.Ignore())
                .ForMember(dest => dest.RevisionDate, opt => opt.Ignore())
                .ForMember(dest => dest.Id, opt => opt.Ignore())
                .ForMember(dest => dest.IsNew, opt => opt.Ignore());

                //.ForMember(dest => dest.IsNew, opt => opt.UseValue(false))

                //.ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.GetGuid(src.GetOrdinal("ContentId"))));

            Mapper.CreateMap<DbContentType, ContentType>()
                .ForMember(dest => dest.Parameters, opt => opt.MapFrom(src =>
                    {
                        return src.ContentTypeParameters.ToDictionary(kvp => kvp.ParameterName, kvp => kvp.ParameterValue);
                    }));
        }
    }
}
